package com.peppa.sirius.esaml.design;


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;

import com.peppa.xtext.esaml.esaml.AccessChannel;
import com.peppa.xtext.esaml.esaml.ActivitySubComponent;
import com.peppa.xtext.esaml.esaml.ComponentImpl;
import com.peppa.xtext.esaml.esaml.DataComponentType;
import com.peppa.xtext.esaml.esaml.EnumType;
import com.peppa.xtext.esaml.esaml.EnumVariable;
import com.peppa.xtext.esaml.esaml.Operation;
import com.peppa.xtext.esaml.esaml.Property;
import com.peppa.xtext.esaml.esaml.RefComponent;
import com.peppa.xtext.esaml.esaml.Reference;
import com.peppa.xtext.esaml.esaml.ReferenceEnum;
import com.peppa.xtext.esaml.esaml.StateSubComponent;
import com.peppa.xtext.esaml.esaml.SubComponent;
import com.peppa.xtext.esaml.esaml.Variable;
import com.peppa.xtext.esaml.esaml.impl.AccessChannelImpl;
import com.peppa.xtext.esaml.esaml.impl.ActivityImplImpl;
import com.peppa.xtext.esaml.esaml.impl.ActivitySubComponentImpl;
import com.peppa.xtext.esaml.esaml.impl.BASE_TYPEImpl;
import com.peppa.xtext.esaml.esaml.impl.CompositeTypeImpl;
import com.peppa.xtext.esaml.esaml.impl.DataComponentTypeImpl;
import com.peppa.xtext.esaml.esaml.impl.DataSubComponentImpl;
import com.peppa.xtext.esaml.esaml.impl.EnumTypeImpl;
import com.peppa.xtext.esaml.esaml.impl.EnumVariableImpl;
import com.peppa.xtext.esaml.esaml.impl.MonitorSubComponentImpl;
import com.peppa.xtext.esaml.esaml.impl.OperationImpl;
import com.peppa.xtext.esaml.esaml.impl.OperationsImpl;
import com.peppa.xtext.esaml.esaml.impl.ReferenceEnumImpl;
import com.peppa.xtext.esaml.esaml.impl.ReferenceImpl;
import com.peppa.xtext.esaml.esaml.impl.StateImplImpl;
import com.peppa.xtext.esaml.esaml.impl.StateSubComponentImpl;
import com.peppa.xtext.esaml.esaml.impl.SubSystemImplImpl;
import com.peppa.xtext.esaml.esaml.impl.SubSystemSubComponentImpl;
import com.peppa.xtext.esaml.esaml.impl.SubSystemTypeImpl;
import com.peppa.xtext.esaml.esaml.impl.SystemImplImpl;
import com.peppa.xtext.esaml.esaml.impl.SystemTypeImpl;
import com.peppa.xtext.esaml.esaml.impl.TimeTriggerSubComponentImpl;
import com.peppa.xtext.esaml.esaml.impl.VariableImpl;
import com.peppa.xtext.esaml.esaml.impl.VariableTypeImpl;

public class PropertiesViewServices{
	
	/**
	 * 移除引用变量的名字
	 * @param self
	 * @param selectCollection
	 * @return
	 */
	public EList<String> removeRefererceRefNames(Reference self, Collection<String> selectCollection) {
		ReferenceImpl referenceImpl = (ReferenceImpl) self;
		EList<String> refNameEList = referenceImpl.getRefName();
		refNameEList.removeAll((ArrayList<String>) selectCollection);
		return null;
	}
	
	/**
	 * 移除引用枚举变量的名字
	 * @param self
	 * @param selectCollection
	 * @return
	 */
	public EList<String> removeRefererceEnumRefNames(ReferenceEnum self, Collection<String> selectCollection) {
		ReferenceEnumImpl referenceEnumImpl = (ReferenceEnumImpl) self;
		EList<String> refNameEList = referenceEnumImpl.getRefName();
		refNameEList.removeAll((ArrayList<String>) selectCollection);
		return null;
	}
	
	/**
	 * 设置引用组件类型关键字
	 * @param self
	 * @param componentType
	 * @return
	 */
	public String setRefComponentTypeKeyWord(Reference self) {
		ReferenceImpl referenceImpl = (ReferenceImpl) self;
		RefComponent refComponent =  referenceImpl.getRefComponentType();
		System.out.println(refComponent);
		if(refComponent instanceof SystemTypeImpl) {
			referenceImpl.setRefKeyWord("system");
			return null;
		}else if(refComponent instanceof SubSystemTypeImpl) {
			referenceImpl.setRefKeyWord("subsystem");
			return null;
		}
		referenceImpl.setRefKeyWord("activity");
		return null;
	}
	
	/**
	 * 设置引用枚举组件类型关键字
	 * @param self
	 * @return
	 */
	public String setRefEnumComponentTypeKeyWord(ReferenceEnum self) {
		ReferenceEnumImpl referenceEnumImpl = (ReferenceEnumImpl) self;
		RefComponent refComponent =  referenceEnumImpl.getRefComponentType();
//		System.out.println(refComponent);
		if(refComponent instanceof SystemTypeImpl) {
			referenceEnumImpl.setRefKeyWord("system");
			return null;
		}else if(refComponent instanceof SubSystemTypeImpl) {
			referenceEnumImpl.setRefKeyWord("subsystem");
			return null;
		}
		referenceEnumImpl.setRefKeyWord("activity");
		return null;
	}
	
	/**
	 * 设置引用变量的类型
	 * @param self
	 * @return
	 * @throws SecurityException 
	 * @throws NoSuchMethodException 
	 * @throws IllegalArgumentException 
	 * @throws InvocationTargetException 
	 * @throws InstantiationException 
	 * @throws IllegalAccessException 
	 */
	public String setRefVariableType(Reference self) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//		System.out.println("1");
		
		Constructor<VariableTypeImpl> constructor = VariableTypeImpl.class.getDeclaredConstructor();
		constructor.setAccessible(true);
		VariableTypeImpl newVariableTypeImpl = constructor.newInstance();
		
		ReferenceImpl referenceImpl = (ReferenceImpl) self;
		VariableImpl refVariableImpl = (VariableImpl) referenceImpl.getRefVariable();
		VariableTypeImpl refVariableTypeImpl = (VariableTypeImpl) refVariableImpl.getVariableType();
		
		newVariableTypeImpl.setIsArray(refVariableTypeImpl.isIsArray());
		newVariableTypeImpl.setLength(refVariableTypeImpl.getLength());
		
		EObject typeEObject = refVariableTypeImpl.getType();
//		System.out.println("2");
		if(typeEObject instanceof BASE_TYPEImpl) {
			BASE_TYPEImpl base_TYPEImpl = (BASE_TYPEImpl) typeEObject;
//			System.out.println("3");
			
			Constructor<BASE_TYPEImpl> constructorBASE_TYPEImpl = BASE_TYPEImpl.class.getDeclaredConstructor();
			constructorBASE_TYPEImpl.setAccessible(true);
			BASE_TYPEImpl newBASE_TYPEImpl = constructorBASE_TYPEImpl.newInstance();
			newBASE_TYPEImpl.setTypeName(base_TYPEImpl.getTypeName());
//			System.out.println("4");
			newVariableTypeImpl.setType(newBASE_TYPEImpl);
//			System.out.println("5");
			
		}else {
			CompositeTypeImpl compositeTypeImpl = (CompositeTypeImpl) typeEObject;
//			System.out.println("6");
			Constructor<CompositeTypeImpl> constructorCompositeTypeImpl = CompositeTypeImpl.class.getDeclaredConstructor();
			constructorCompositeTypeImpl.setAccessible(true);
			CompositeTypeImpl newCompositeTypeImpl = constructorCompositeTypeImpl.newInstance();
//			System.out.println("7");
			EObject rootElement = EcoreUtil2.getRootContainer(referenceImpl);
	        List<DataComponentType> candidates = EcoreUtil2.getAllContentsOfType(rootElement, DataComponentType.class);
//	        System.out.println("8");
	        for(DataComponentType dataComponentType : candidates) {
	        	DataComponentTypeImpl dataComponentTypeImpl = (DataComponentTypeImpl) dataComponentType;
	        	if(dataComponentTypeImpl.equals(compositeTypeImpl.getDataComponentType())) {
	        		newCompositeTypeImpl.setDataComponentType(dataComponentType);
	        		break;
	        	}
	        }
//	        System.out.println("9");
			
			newVariableTypeImpl.setType(newCompositeTypeImpl);
		}
		
		referenceImpl.setRefVariableType(newVariableTypeImpl);
//		System.out.println("10");

		return null;
	}
	
	/**
	 * 设置引用枚举变量的类型
	 * @param self
	 * @return
	 */
	public String setRefEnumType(ReferenceEnum self){
		
		ReferenceEnumImpl referenceEnumImpl = (ReferenceEnumImpl) self;
		EnumVariableImpl refEnumVariableImpl = (EnumVariableImpl) referenceEnumImpl.getRefEnumVariable();
		
		EObject rootElement = EcoreUtil2.getRootContainer(refEnumVariableImpl);
        List<EnumType> candidates = EcoreUtil2.getAllContentsOfType(rootElement, EnumType.class);
        for(EnumType enumType : candidates) {
        	EnumTypeImpl enumTypeImpl = (EnumTypeImpl) enumType;
        	if(enumTypeImpl.equals(refEnumVariableImpl.getEnumType())) {
        		referenceEnumImpl.setRefEnumType(enumType);
        		break;
        	}
        }
        
		return null;
	}
	
	/**
	 * 获取SubComponentGroup中SubComponentType的引用表达式
	 * @param self
	 * @return
	 */
	public String getSubComponentTypeReferenceNameExpression(SubComponent self) {
		if(self instanceof SubSystemSubComponentImpl) {
			return "subSystemSubComponentType";
		}else if(self instanceof TimeTriggerSubComponentImpl) {
			return "timeTriggerSubComponentType";
		}else if(self instanceof MonitorSubComponentImpl) {
			return "monitorSubComponentType";
		}else if(self instanceof ActivitySubComponentImpl) {
			return "activitySubComponentType";
		}else if(self instanceof StateSubComponentImpl) {
			return "stateSubComponentType";
		}else if(self instanceof DataSubComponentImpl) {
			return "dataSubComponentType";
		}
		
		return null;
	}
	
	/**
	 * 获取SubComponentGroup中SubComponentImpl的引用表达式
	 * @param self
	 * @return
	 */
	public String getSubComponentImplReferenceNameExpression(SubComponent self) {
		if(self instanceof SubSystemSubComponentImpl) {
			return "subSystemSubComponentImpl";
		}else if(self instanceof TimeTriggerSubComponentImpl) {
			return "timeTriggerSubComponentImpl";
		}else if(self instanceof MonitorSubComponentImpl) {
			return "monitorSubComponentImpl";
		}else if(self instanceof ActivitySubComponentImpl) {
			return "activitySubComponentImpl";
		}else if(self instanceof StateSubComponentImpl) {
			return "stateSubComponentImpl";
		}else if(self instanceof DataSubComponentImpl) {
			return "dataSubComponentImpl";
		}
		
		return null;
	}
	
	/**
	 * 获取子系统实现中活动子组件实现的operation
	 * @param self
	 * @return
	 */
	public String getActivitySubComponentImplOperation(ActivitySubComponent self) {
//		System.out.println("进入getActivitySubComponentImplOperation");
		ActivityImplImpl activityImplImpl = (ActivityImplImpl) self.getActivitySubComponentImpl();
		OperationsImpl operationsImpl = (OperationsImpl) activityImplImpl.getOperations();
		if(operationsImpl != null) {
//			System.out.println(operationsImpl.getOperations());
//			System.out.println(operationsImpl.getOperations().get(0).toString());
			return operationsImpl.getOperations().get(0).getOperation();
		}
//		System.out.println(operationsImpl);
		if(activityImplImpl.getStateMachine() != null) {
			return "当前活动实现为状态机";
		}
		return null;
	}
	
	/**
	 * 设置子系统实现中活动子组件实现的operation
	 * @param self
	 * @param value
	 * @return
	 */
	public String setActivitySubComponentImplOperation(ActivitySubComponent self, String value) {
		ActivityImplImpl activityImplImpl = (ActivityImplImpl) self.getActivitySubComponentImpl();
		OperationsImpl operationsImpl = (OperationsImpl) activityImplImpl.getOperations();
		if(operationsImpl != null) {
			List<Operation> operationList = operationsImpl.getOperations();
			OperationImpl operationImpl = (OperationImpl) operationList.get(0);
			operationImpl.setOperation(value);
		}
		return null;
	}
	
	/**
	 * 获取活动实现中状态子组件实现的operation
	 * @param self
	 * @param operationType
	 * @return
	 */
	public String getStateSubComponentImplOperation(StateSubComponent self, String operationType) {
		StateImplImpl stateImplImpl = (StateImplImpl) self.getStateSubComponentImpl();
		if("entry".equals(operationType)) {
			List<Operation> operationList = stateImplImpl.getEntryOperations();
			return operationList.get(0).getOperation();
		}else if("during".equals(operationType)) {
			List<Operation> operationList = stateImplImpl.getDuringOperations();
			return operationList.get(0).getOperation();
		}else if("exit".equals(operationType)) {
			List<Operation> operationList = stateImplImpl.getExitOperations();
			return operationList.get(0).getOperation();
		}
		return null;
	}
	
	/**
	 * 设置活动实现中状态子组件实现的operation
	 * @param self
	 * @param operationType
	 * @param value
	 * @return
	 */
	public String setStateSubComponentImplOperation(StateSubComponent self, String operationType, String value) {
		StateImplImpl stateImplImpl = (StateImplImpl) self.getStateSubComponentImpl();
		if("entry".equals(operationType)) {
			List<Operation> operationList = stateImplImpl.getEntryOperations();
			OperationImpl operationImpl = (OperationImpl) operationList.get(0);
			operationImpl.setOperation(value);
		}else if("during".equals(operationType)) {
			List<Operation> operationList = stateImplImpl.getDuringOperations();
			OperationImpl operationImpl = (OperationImpl) operationList.get(0);
			operationImpl.setOperation(value);
		}else if("exit".equals(operationType)) {
			List<Operation> operationList = stateImplImpl.getExitOperations();
			OperationImpl operationImpl = (OperationImpl) operationList.get(0);
			operationImpl.setOperation(value);
		}
		return null;
	}
	
	
	/**
	 * 移除AccessChannel中要访问的目标DataComponent的某些属性
	 * @param self
	 * @param selectCollection
	 * @return
	 */
	public EList<String> removeAccessChannelDataProperties(AccessChannel self, Collection<String> selectCollection) {
		AccessChannelImpl accessChannelImpl = (AccessChannelImpl) self;
		EList<String> dataPropertiesEList = accessChannelImpl.getDataProperties();
		dataPropertiesEList.removeAll((ArrayList<String>) selectCollection);
		return null;
	}
	
	/**
	 * 获取组件实现的Property,返回Property的表示字符串
	 * @param self
	 * @return
	 */
	public String getModelImplPropertieString(Property self) {
		Services services = new Services();
		StringBuilder labelString = new StringBuilder();
		if(self instanceof VariableImpl) {
			labelString.append(services.getVariable_Name_Type((Variable) self));
		}else if (self instanceof EnumVariableImpl) {
			labelString.append(services.getEnumVariable_Name_Type((EnumVariable) self));
		}else if (self instanceof ReferenceImpl) {
			labelString.append(services.getReference_Name_Type((Reference) self));
		}else if (self instanceof ReferenceEnumImpl) {
			labelString.append(services.getReferenceEnum_Name_Type((ReferenceEnum) self));
		}
		return labelString.toString();
	}
	
	/**
	 * 移除组件实现中的某些属性
	 * @param self
	 * @param selectCollection
	 * @return
	 */
	public EList<String> removeProperty(ComponentImpl self, Collection<Property> selectCollection) {
		EList<Property> propertiesEList = null;
		if(self instanceof SystemImplImpl) {
			SystemImplImpl systemImplImpl = (SystemImplImpl) self;
			propertiesEList = systemImplImpl.getProperties();
		}else if (self instanceof SubSystemImplImpl) {
			SubSystemImplImpl subSystemImplImpl = (SubSystemImplImpl) self;
			propertiesEList = subSystemImplImpl.getProperties();
		}else if (self instanceof ActivityImplImpl) {
			ActivityImplImpl activityImplImpl = (ActivityImplImpl) self;
			propertiesEList = activityImplImpl.getProperties();
		}
		propertiesEList.removeAll((ArrayList<Property>) selectCollection);
		return null;
	}
	
}